<script lang="ts" setup>
import { computed, h, reactive, ref, watch } from 'vue'
import { RedoOutlined } from '@ant-design/icons-vue'
import { type TableColumnType, type TablePaginationConfig, type TableProps, message } from 'ant-design-vue'
import type { FilterValue, SorterResult } from 'ant-design-vue/es/table/interface'

import { useI18n } from 'vue-i18n'
import CreateTaskDrawer from './CreateTaskDrawer.vue'
import AffectedHostDrawer from './AffectedHostDrawer.vue'
import type { HostInfoInCve, HostsInCve } from './CveTask.vue'
import CveTask from './CveTask.vue'
import TaskModal from './TaskModal.vue'
import type { Cve } from '@/api'

const props = defineProps<{
  hostInfo?: HostInfoInCve
  isFixed: boolean
  tableColumns?: TableColumnType[]
  tableData: Cve[]
  expandTableColumns?: TableColumnType[]
  pagination: TablePaginationConfig
  loading?: boolean
  rowSelection?: {
    selectedRowKeys: any[]
    onSelect: (record: CveTableItem, selected: boolean) => void
    onSelectAll: (selected: boolean, selectedRows: CveTableItem[]) => void
  }
  expandRowSelection?: {
    selectedRowKeys: any[]
    onSelect: (record: Rpm, selected: boolean, selectedRows: unknown) => void
    onSelectAll: (selected: boolean, selectedRows: unknown, changeRows: unknown) => void
    getCheckboxProps?: any
  }
}>()
const emit = defineEmits<{
  (e: 'expand', expanded: boolean, record: CveTableItem): void
  (
    e: 'change',
    page: TablePaginationConfig,
    filters: Record<string, FilterValue | null>,
    sorter: SorterResult<CveTableItem> | SorterResult<CveTableItem>[],
    searchKey?: string
  ): void
  (e: 'radioChange', check: boolean)
  (e: 'clear')
}>()
const { t } = useI18n()
export interface Rpm {
  cve_id?: string
  available_rpm: string
  installed_rpm: string
  host_num: number
  support_way: string
}

export interface CveTableItem {
  cve_id: string
  cvss_score: string
  description: string
  host_num?: number
  package: string
  publish_time: string
  severity: string
  rpms?: Rpm[]
}
const tableState = reactive<{
  selectedRowKeys: string[]
  loading: boolean
  expandedRowKeys: string[]
  isDrawerVisible: boolean
  isSuccessModalVisible: boolean
  countdown: number
}>({
  selectedRowKeys: [],
  loading: false,
  expandedRowKeys: [],
  isDrawerVisible: false,
  isSuccessModalVisible: false,
  countdown: 0,
})

const cveList = computed(() => {
  return props.tableData?.filter(i => props.rowSelection?.selectedRowKeys.includes(i.cve_id)).map(c => ({
    ...c,
    rpms: c.rpms?.filter(r => props.expandRowSelection?.selectedRowKeys.includes(`${r.cve_id}-${r.installed_rpm}-${r.available_rpm}`)),
  }))
},
)

const hostListInCve = computed<HostsInCve[]>(() => {
  if (!props.hostInfo)
    return []
  const list = props.tableData?.filter(i =>
    props.rowSelection?.selectedRowKeys.includes(i.cve_id),
  )
  return list.map(item => ({
    cve_id: item.cve_id,
    hosts: [props.hostInfo!],
  }))
})

function onExpand(expanded: boolean, record: CveTableItem) {
  emit('expand', expanded, record)
}

const searchKey = ref<string | undefined>()

const onChange: TableProps<CveTableItem>['onChange'] = (page, filters, sorter) => {
  tableState.expandedRowKeys = []
  emit('change', page, filters, sorter, searchKey.value)
}

function onSearch() {
  tableState.expandedRowKeys = []
  emit(
    'change',
    { current: 1, pageSize: 10 },
    { severity: null },
    {},
    searchKey.value,
  )
}

const taskTypeMap = computed(() => ({
  'hotpatch remove': t('vul.hotPatchRemove'),
  'cve fix': t('vul.generateFixTask'),
}))

const taskType = computed(() => (props.isFixed ? 'hotpatch remove' : 'cve fix'))

function refresh() {
  searchKey.value = ''
  onSearch()
}
const taskModalTitle = ref('')

const modalType = ref<'success' | 'warn'>('success')
function handleSuccess(type: 'success' | 'warn', msg: string) {
  if (type === 'warn') {
    tableState.isDrawerVisible = false
    return
  }

  taskModalTitle.value = msg
  modalType.value = type
  tableState.isDrawerVisible = false
  tableState.isSuccessModalVisible = true
}

function handleDrawerTrigger() {
  if (props.tableData.length === 0)
    return message.info(`${t('vul.cves.message.atLeastOne', { type: taskType.value === 'cve fix' ? t('vul.fix') : t('vul.remove') })}`)

  tableState.isDrawerVisible = true
}

watch(
  () => tableState.isSuccessModalVisible,
  () => refresh(),
)
</script>

<template>
  <a-row type="flex" justify="space-between">
    <a-col>
      <a-row type="flex" :gutter="16">
        <a-col>
          <a-radio-group
            :value="isFixed"
            button-style="solid"
            @change="
              () => {
                tableState.expandedRowKeys = [];
                searchKey = undefined;
                emit('radioChange', !isFixed);
              }
            "
          >
            <a-radio-button :value="false">
              {{ t('vul.unfixed') }}
            </a-radio-button>
            <a-radio-button :value="true">
              {{ t('vul.fixed') }}
            </a-radio-button>
          </a-radio-group>
        </a-col>
        <a-col>
          <a-input-search
            v-model:value="searchKey"
            :placeholder="t('vul.cves.placeHolder.searchBy')"
            :maxlength="40"
            @search="onSearch"
          />
        </a-col>
      </a-row>
    </a-col>
    <a-col>
      <a-row type="flex" :gutter="6">
        <a-col v-if="rowSelection && rowSelection.selectedRowKeys.length > 0">
          <a-alert type="info" show-icon class="delete-alert">
            <template #message>
              <span>{{ t('common.selectItems', { count: rowSelection.selectedRowKeys.length }) }}</span>
              <a-divider type="vertical" />
              <a @click="$emit('clear')"> {{ t('common.clear') }}</a>
            </template>
          </a-alert>
        </a-col>
      </a-row>
    </a-col>
    <a-col>
      <a-space>
        <slot name="header-button" />
        <CreateTaskDrawer
          :title="taskTypeMap[taskType]"
          :visible="tableState.isDrawerVisible"
          @close="tableState.isDrawerVisible = false"
        >
          <template #trigger>
            <a-button type="primary" @click="handleDrawerTrigger">
              {{
                taskTypeMap[taskType]
              }}
            </a-button>
          </template>
          <template #content>
            <CveTask
              :task-type="taskType"
              :cve-list="cveList"
              :host-list-in-cve="hostListInCve"
              :is-fixed="isFixed"
              @cancel="tableState.isDrawerVisible = false"
              @close="tableState.isDrawerVisible = false"
              @success="
                handleSuccess
              "
            />
          </template>
        </CreateTaskDrawer>
        <a-button style="width: 50px" :icon="h(RedoOutlined)" @click="refresh" />
      </a-space>
    </a-col>
  </a-row>
  <a-table
    v-model:expandedRowKeys="tableState.expandedRowKeys"
    row-key="cve_id"
    :columns="tableColumns"
    :data-source="tableData"
    :pagination="pagination"
    :row-selection="rowSelection"
    :loading="loading"
    @expand="onExpand"
    @change="onChange"
  >
    <template v-if="expandTableColumns" #expandedRowRender="{ record }">
      <p>Description:</p>
      <p>{{ record.description }}</p>
      <a-table
        :row-key="(inner:Rpm) => `${record.cve_id}-${inner.installed_rpm}-${inner.available_rpm}`"
        :columns="expandTableColumns"
        :data-source="record.rpms"
        :pagination="false"
        :loading="!record.rpms"
        :row-selection="expandRowSelection"
      >
        <template #bodyCell="{ record: expandRecord, column }">
          <template v-if="column.dataIndex === 'host_num'">
            <AffectedHostDrawer :fixed="isFixed" :cve-id="record.cve_id" :rpm-info="expandRecord">
              <template #trigger>
                <a>{{ expandRecord.host_num }}</a>
              </template>
            </AffectedHostDrawer>
          </template>
          <template v-if="column.dataIndex === 'fixed_way'">
            {{ expandRecord.fixed_way }} {{ expandRecord.hp_status ? `(${expandRecord.hp_status})` : '' }}
          </template>
        </template>
      </a-table>
    </template>
    <template #bodyCell="{ record, column }">
      <template v-if="column.dataIndex === 'cve_id'">
        <router-link :to="{ path: `/vulnerability/cves/cve-detail/${record.cve_id}` }">
          {{ record.cve_id }}
        </router-link>
      </template>
    </template>
  </a-table>

  <TaskModal
    v-model:visible="tableState.isSuccessModalVisible"
    :type="modalType"
    :title="taskModalTitle"
  />
</template>
